BUTTONS ------------------------------------------------------------- Buttons are things that you attach to frames. Pressing a button (by pointing with the mouse cursor and pressing the left mouse button) is an event, so a button must have an associated event-handler. void definesquarebuttontext(imagestkptr ifs, unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned rx, unsigned ry, char *msg, callproc event); This will draw a square button on the frame ifs. x1, y1, x2, y2 are relative coordinates on the frame where the button will be drawn. rx and ry are offsets to draw the text msg at. Event is the event-handler to call when the button is pressed. char visualsqarebuttonpress(imagestkptr ifs, msclickptr ms); This function presses a squarebutton down and then returns TRUE if the mouse button was released while the mouse pointer was over the button. This function should be called from within an event-handler and would be passed the same parameters that were passed to the event-handler. The event-handler would use the return value to determine if an action is required (i.e. if TRUE). If so then the first thing that should be done is a call to releasesquarebutton which will pop the button back up. If visualsquarebuttonpress returns FALSE then releasesquarebutton is called automatically and the event-handler should not call it. void releasesquarebutton(imagestkptr ifs, msclickptr ms); This will release a button that was previously pressed by visualsquarebuttonpress. This example shows the complete use of a button attached to a frame. When the button is pressed and released then the frame is disposed of. BEGINFILE> button1.c /* -- button1.c */ #include "teglsys.h" imagestkptr ifs; unsigned cancelevent(imagestkptr frame, msclickptr mouse) { /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ releasesquarebutton(frame,mouse); /* -- and dispose of the frame. */ dropstackimage(ifs); } return 0; } void main(void) { easytegl(); easyout(); pushimage(50,50,200,150); shadowbox(50,50,200,150); ifs = stackptr; definesquarebuttontext(ifs,30,35,120,65,5,5,"PRESS ME",cancelevent); teglsupervisor(); } ENDFILE> Buttons can have more than text displayed on them. In true GUI fashion buttons might have appropriate icons displayed on them to indicate their purpose. void definesquarebuttonclick(imagestkptr ifs, unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned rx, unsigned ry, char *button, callproc event); definesquarebuttonclick is the same as definesquarebuttontext above except that an icon is displayed on the button instead of text. This example creates a frame with squarebutton that shows a lightbulb icon. BEGINFILE> button2.c /* -- button2.c */ #include "teglsys.h" imagestkptr ifs; unsigned cancelevent(imagestkptr frame, msclickptr mouse) { /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ releasesquarebutton(frame,mouse); /* -- and dispose of the frame. */ dropstackimage(ifs); } return 0; } void main(void) { easytegl(); easyout(); pushimage(50,50,200,150); shadowbox(50,50,200,150); ifs = stackptr; definesquarebuttonclick(ifs,30,35,120,65,35,5,imageBULB,cancelevent); teglsupervisor(); } ENDFILE> It may be useful at some time to have a button floating around by itself. The easyout button that is displayed at the bottom right corner of the screen is just such a button. In fact it is a frame with a button that is the full size of the frame. We can use these for other purposes. This example places two floating buttons on the screen, one with a 5.25" floppy disk icon and the other with a 3.5" floppy disk icon. BEGINFILE> button3.c /* -- button3.c */ #include "teglsys.h" unsigned disk35event(imagestkptr frame, msclickptr mouse) { /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ releasesquarebutton(frame,mouse); } return 0; } unsigned diskevent(imagestkptr frame, msclickptr mouse) { /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ /* ReleaseSquareButton(frame,mouse); */ } return 0; } void main(void) { easytegl(); easyout(); pushimage(0,9,39,49); definesquarebuttonclick(stackptr,0,0,39,39,5,5,imageDISK,diskevent); pushimage(0,49,39,89); definesquarebuttonclick(stackptr,0,0,39,39,5,5,imageDISK35,disk35event); teglsupervisor(); } ENDFILE> One of the things that can go wrong is forgetting to release a square button once it is pressed. Try commenting out one of the releasesquarebutton calls from the previous program and see what happens when the button is pressed repeatedly. The next example gives a complete illustration of a floating button that opens up a window to do something. Important items to note here are: * the use of a control variable to keep track of a frame that you don't want more than one instance running. * setting the viewport to cover a frame, you don't have to calculate the relative displacement for text or graphics then. * using more than one button on a frame. Each with its own event. BEGINFILE> button4.c /* -- button4.c */ #include "teglsys.h" /* -- a control variable to make sure that only one instance of the */ /* -- format frame is displayed */ unsigned char formatinstance = FALSE; unsigned formatevent(imagestkptr frame, msclickptr mouse) { if (visualsquarebuttonpress(frame,mouse)) { releasesquarebutton(frame,mouse); setviewport(0,0,getmaxx(),getmaxy(),FALSE); errmess(getmaxx() / 4,getmaxy() / 4,"Function not compete!"); } return 0; } unsigned cancelevent(imagestkptr frame, msclickptr mouse) { if (visualsquarebuttonpress(frame,mouse)) { releasesquarebutton(frame,mouse); dropstackimage(frame); formatinstance = FALSE; } return 0; } unsigned diskevent(imagestkptr frame, msclickptr mouse) { imagestkptr ifs; unsigned x1 = 100; unsigned y1 = 100; unsigned x2 = 200; unsigned y2 = 100; /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ releasesquarebutton(frame,mouse); if (formatinstance) { setviewport(0,0,getmaxx(),getmaxy(),FALSE); errmess(200,100,"The format window is open"); return 0; } formatinstance = TRUE; setviewport(0,0,getmaxx(),getmaxy(),FALSE); /* -- fullscreen */ /* -- upper corner */ quickframe(&ifs,&x1, &y1, &x2, &y2); /* -- width & height */ setteglfont(font14); /* -- setting the viewport to the frame makes it easy */ /* -- for outputting text and graphics. */ prepareforupdate(ifs); setviewport(ifs->x,ifs->y,ifs->x1,ifs->y1,TRUE); settextjustify(CENTER_TEXT,TOP_TEXT); outtextxy(100,20,"Format a disk?"); settextjustify(LEFT_TEXT,TOP_TEXT); commitupdate(); definesquarebuttontext(ifs,20,70,60,90,10,5,"OK",formatevent); definesquarebuttontext(ifs,110,70,180,90,10,5,"CANCEL",cancelevent); } return 0; } void main(void) { easytegl(); easyout(); setautorotate(TRUE); pushimage(0,9,39,49); definesquarebuttonclick(stackptr,0,0,39,39,6,4,imageDISK,diskevent); setteglfont(f5x6norm); setcolor(BLACK); outtextxy(4,33,"Format"); outtextxy(9,40,"Disk"); teglsupervisor(); } ENDFILE> This example illustrates how mouse click numbers are associated with a button. It draws frame with fifty number buttons on it that display their button numbers when clicked on. This shows how easy it is to set up a matrix of buttons. The important part of this program is how the event-handler (shownumber) can determine which button was pressed. Consider how straight forward it would be to implement a calculator. BEGINFILE> button5.c /* -- button5.c */ #include "teglsys.h" unsigned shownumber( imagestkptr frame, msclickptr mouse ) { char s[25]; /* -- if true then the button has been released */ if (visualsquarebuttonpress(frame,mouse)) { /* -- this will pop the button back up */ releasesquarebutton(frame,mouse); prepareforupdate(frame); setviewport(frame->x,frame->y,frame->x1,frame->y1,TRUE); setfillstyle(SOLID_FILL,WHITE); bar(5,110,210,130); setteglfont(f8x12bol); /* -- the mouse pointer contains what clicknumber it was */ /* -- assigned to. */ setcolor(BLACK); outtextxy(5,112,"Button "); itoa(mouse->clicknumber,s,10); outtextxy(70,112,s); commitupdate(); } return 0; } void buttonbunch(void) { int i, xd, yd; imagestkptr ifs; unsigned x1 = 100; unsigned y1 = 100; unsigned x2 = 222; unsigned y2 = 140; char s[25]; setviewport(0,0,getmaxx(),getmaxy(),FALSE); quickframe(&ifs,&x1,&y1,&x2,&y2); xd = 0; yd = 0; for (i = 1; i <= 50; i++) { /* -- as we define each button we put its clicknumber on it */ /* -- note that MsClickCount would only be the correct on return */ /* -- so we add one to it. */ setteglfont(f7x7bold); itoa(+ifs->msclickcount + 1,s,10); definesquarebuttontext(ifs,xd,yd,xd + 20,yd + 20,3,8,s,shownumber); xd = xd + 22; if (xd > 200) { xd = 0; yd = yd + 22; } } } void main(void) { easytegl(); easyout(); buttonbunch(); teglsupervisor(); } ENDFILE> Things to remember! * Square button arguments are RELATIVE to the frame they are being attached to. * A square button is just another mouse click on a frame. The imagestkptr that is passed to definesquarebuttonclick or definesquarebuttontext will contain the clicknumber of the on return in the msclickcount field. * You can make floating buttons by making the button and the frame the same size. * Beware of viewport settings. Many routines assume that the viewport and text settings are the startup defaults. If in doubt do a setviewport(0,0,getmaxx(),getmaxy(),0) and settextjustify(LEFT_TEXT,TOP_TEXT); ---------------------------------------------------------- END buttons.txt